home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume8 / bug < prev    next >
Encoding:
Text File  |  1989-09-30  |  9.3 KB  |  332 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v08i064: bug -- make a transcript of a socket connection
  3. from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  4. Reply-To: matthew@CS.UCLA.EDU (Matthew Merzbacher)
  5.  
  6. Posting-number: Volume 8, Issue 64
  7. Submitted-by: matthew@CS.UCLA.EDU (Matthew Merzbacher)
  8. Archive-name: bug
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    README
  16. #    bug.1
  17. #    bug.c
  18. # This archive created: Fri Sep 29 18:29:52 1989
  19. export PATH; PATH=/bin:$PATH
  20. if test -f 'README'
  21. then
  22.     echo shar: will not over-write existing file "'README'"
  23. else
  24. cat << \SHAR_EOF > 'README'
  25. Bug is used to tap a stream socket.  It is useful for tracing communication 
  26. between a server and its clients.  The communication between server and
  27. client is maintained while transcripts of all communication lines are taken.
  28.  
  29. There is a man page (bug.1), a source file (bug.c) and this file (README)
  30. included in this archive.  No Makefile is necessary, since to "make" it, all
  31. you do is:
  32.     cc -o bug bug.c
  33.  
  34. You need to be running a BSD or BSD-derived system (since it examines sockets).
  35. It has been tested under SunOS 4.0.3
  36.  
  37. If you don't like my MARK, you can change it by changing the lines
  38. #define MARK
  39. and
  40. #define MARKLEN
  41. to your own values.
  42.  
  43. I'd be interested in hearing what people have to say and what they use 'bug'
  44. for.  I hope I haven't re-invented the wheel.  Bugs/Comments/Questions/Hate 
  45. Mail to me,
  46.  
  47. Matthew Merzbacher    ARPA:    matthew@CS.UCLA.EDU
  48.               UUCP:    ...!{uunet|rutgers|ucbvax}!cs.ucla.edu!matthew
  49. SHAR_EOF
  50. fi # end of overwriting check
  51. if test -f 'bug.1'
  52. then
  53.     echo shar: will not over-write existing file "'bug.1'"
  54. else
  55. cat << \SHAR_EOF > 'bug.1'
  56. .TH BUG 1
  57. \" Copyright (C) 1989 by Matthew Merzbacher.  All Rights Reserved.
  58. .SH NAME
  59. bug \- listen and transcribe communication on a socket
  60. .SH SYNOPSIS
  61. .B bug
  62. .nh
  63. input_port output_port machine client_file server_file
  64. .hy
  65. .SH DESCRIPTION
  66. .I bug
  67. is used to listen on a specified \fIinput_port\fR and write an exact
  68. duplicate out to the \fIoutput_port\fR on a specified \fImachine\fR.  It 
  69. also writes a transcript of everything that is said on either port
  70. to seperate files.  Each piece of communication is seperated by a MARK, which
  71. is #defined in the code as "<MARK>".
  72. .PP
  73. The naming scheme for the output files is \fIclient_file\fR (for communication
  74. received from the \fIinput_port\fR) or \fIserver_file\fR (for communication 
  75. received from the \fIoutput_port\fR) followed by a period ('.') followed by 
  76. the process id of the bug program followed by a period ('.') followed by the 
  77. process id of the child of bug which actually does the monitoring.  Thus, for 
  78. every connection made to the input_port, there will be two (unique) files 
  79. created.
  80. .PP
  81. The output files are probably best read by using \fIod\fR(1) with the "-c" 
  82. or "-cx" options.
  83. .SH EXAMPLE
  84. \fIbug\fR 3000 2999 moosebreath cl se
  85. .PP
  86. This invocation will create, for every connection to port 3000 on the current 
  87. machine, two files (cl.pid.cpid and se.pid.cpid).  Every communication to port
  88. 3000 is repeated verbatim to port 2999 on machine "moosebreath" and written to
  89. the first file.  All responses are written to the second file.
  90. .SH FILES
  91. .br
  92. creates files based on \fIclient_file\fR and \fIserver_file\fR
  93. .SH "SEE ALSO"
  94. od(1), socket(2) [and friends], fork(2).
  95. .SH AUTHOR
  96. Matthew Merzbacher, bugs/comments - matthew@cs.ucla.edu
  97. .SH BUGS
  98. .PP
  99. Goodness knows what systems this will actually run on.  Any BSD or 
  100. BSD-derived system SHOULD work.
  101.  
  102. There should be an option to change the MARK.
  103. SHAR_EOF
  104. fi # end of overwriting check
  105. if test -f 'bug.c'
  106. then
  107.     echo shar: will not over-write existing file "'bug.c'"
  108. else
  109. cat << \SHAR_EOF > 'bug.c'
  110. /* Copyright (C) 1989 by Matthew Merzbacher.
  111.    All Rights Reserved.
  112.    Bug is provided as is, without express or implied warranty.  In no event
  113.    shall Matthew Merzbacher become liable for any loss or damages, consequential
  114.    or otherwise, arising from the use or possession of this software.
  115. */
  116.  
  117. #include <sys/types.h>
  118. #include <sys/socket.h>
  119. #include <netinet/in.h>
  120. #include <netdb.h>
  121. #include <stdio.h>
  122. #include <fcntl.h>
  123.  
  124. #define MARK "<MARK>"
  125. #define MARKLEN 6
  126.  
  127. /*
  128.  * Brief Description:
  129.  * Bug is used to tap a stream socket.  It is useful for tracing communication 
  130.  * between a server and its clients.  The communication between server and
  131.  * client is maintained while transcripts of all communication lines are taken.
  132.  * It has six required (and no optional) arguments.  
  133.  *
  134.  * Usage:
  135.  * bug <in port> <out port> <machine> <client file> <server file>
  136.  *
  137.  * <in port>     - the port (on the machine on which bug runs) to which to
  138.  *                   clients will connect (the pseudo-port)
  139.  * <out port>    - the true server port
  140.  * <machine>     - the server machine
  141.  * <client file> - transcript file of what each client says
  142.  * <server file> - transcript file of what the server responds
  143.  *
  144.  * Example: 
  145.  * Suppose a server listens on port 3000 of machine "xyz".  The user must 
  146.  * artificially make the clients talk to some other port (on any machine -
  147.  * it could be the server machine, the client machine, or a third machine).
  148.  * That port is called the pseudo-port.  Bug runs on the machine of the
  149.  * pseudo-port.  To run it, type:
  150.  * 
  151.  * bug 2999 3000 xyz client server
  152.  *
  153.  * This assumes that the pseudo-port is 2999.  The output files will all start
  154.  * with "client" or "server" followed by the process number of the bug process
  155.  * and the process number of each seperate listening session.  That way, you
  156.  * can follow the connection order.  Typically, the output files created by bug
  157.  * may be read by using 'od -c'.
  158.  *
  159.  */
  160.  
  161. main(argc, argv)
  162. int argc; char *argv[];
  163. {
  164.     struct sockaddr_in server;
  165.     struct hostent *hp, *gethostbyname();
  166.     char buf[1024];
  167.     int rval;
  168.     int outfile1, outfile2;
  169.     int insock, outsock, msgsock;
  170.     int insocknum, outsocknum;
  171.     fd_set fdset;
  172.  
  173.  
  174.     /* Check Arguments */
  175.  
  176.     if (argc < 6) {
  177.     printf("usage: %s <in port> <out port> <machine> <client file> <server file>\n",argv[0]);
  178.     exit(1);
  179.     }
  180.  
  181.     insocknum = atoi(argv[1]);
  182.     outsocknum = atoi(argv[2]);
  183.  
  184.  
  185.     /* Create listening post on pseudo-port */
  186.  
  187.     insock = socket(AF_INET, SOCK_STREAM, 0);
  188.  
  189.     if (insock < 0) {
  190.     perror("opening pseudo-port stream socket");
  191.     exit(1);
  192.     }
  193.  
  194.  
  195.     /* Name socket using user supplied port number */
  196.  
  197.     server.sin_family = AF_INET;
  198.     server.sin_addr.s_addr = INADDR_ANY;
  199.     server.sin_port = insocknum;
  200.  
  201.     if (bind(insock, &server, sizeof(server))) {
  202.     perror("binding pseudo-port stream socket");
  203.     exit(1);
  204.     }
  205.  
  206.  
  207.     /* Start accepting connections */
  208.  
  209.     listen(insock, SOMAXCONN);
  210.  
  211.  
  212.     /* Every connection spawns a child to handle the communication */
  213.  
  214.     do {
  215.     msgsock = accept(insock, 0, 0);
  216.     if (msgsock == -1)
  217.         perror("accept");
  218.     } while (fork() != 0);
  219.  
  220.  
  221.     /* Close listening post - it's now called "msgsock" */
  222.  
  223.     close(insock);
  224.  
  225.  
  226.     /* Create output socket to server */
  227.  
  228.     outsock = socket(AF_INET, SOCK_STREAM, 0);
  229.     if (outsock < 0) {
  230.     perror("opening server stream socket");
  231.     exit(1);
  232.     }
  233.  
  234.  
  235.     /* Connect socket using machine & port specified on command line. */
  236.  
  237.     server.sin_family = AF_INET;
  238.     hp = gethostbyname(argv[3]);
  239.     if (hp == 0) {
  240.     fprintf(stderr, "%s: unknown machine\n", argv[3]);
  241.     exit(2);
  242.     }
  243.  
  244.     bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
  245.     server.sin_port = htons(outsocknum);
  246.  
  247.     if (connect(outsock, &server, sizeof(server)) < 0) {
  248.     perror("connecting server stream socket");
  249.     exit(1);
  250.     }
  251.  
  252.  
  253.     /* Open the output files */
  254.  
  255.     sprintf(buf,"%s.%d.%d",argv[4],getppid(),getpid());
  256.     if ((outfile1 = open(buf, O_TRUNC|O_WRONLY|O_CREAT, 0644)) == -1) {
  257.     fprintf(stderr,"cannot open file: %s\n",buf);
  258.     exit(1);
  259.     }
  260.  
  261.     sprintf(buf,"%s.%d.%d",argv[5],getppid(),getpid());
  262.     if ((outfile2 = open(buf, O_TRUNC|O_WRONLY|O_CREAT, 0644)) == -1) {
  263.     fprintf(stderr,"cannot open file: %s\n",buf);
  264.     exit(1);
  265.     }
  266.  
  267.     do {
  268.     
  269.     /* find out who's talking */
  270.  
  271.     FD_ZERO(&fdset);
  272.     FD_SET(msgsock, &fdset);
  273.     FD_SET(outsock, &fdset);
  274.     if (select(getdtablesize(), &fdset, 0, 0, 0) == -1) {
  275.         perror("select");
  276.         exit(1);
  277.         }
  278.     bzero(buf, 1024);
  279.  
  280.     if (FD_ISSET(msgsock, &fdset) && FD_ISSET(outsock, &fdset))
  281.         fprintf(stderr,"Two talkers - no listeners\n");
  282.  
  283.  
  284.     /* Client is talking to server */
  285.  
  286.     if (FD_ISSET(msgsock, &fdset)) { 
  287.         if ((rval = read(msgsock, buf, 1024)) < 0)
  288.         perror("reading stream message");
  289.         if (rval == 0)
  290.         fprintf(stderr,"Ending client connection\n");
  291.         else {
  292.         write(outfile1, buf, rval);
  293.         write(outfile1, MARK, 6);
  294.         if (write(outsock, buf, rval) < 0)
  295.             perror("writing on output stream socket");
  296.         }
  297.         }
  298.  
  299.     /* Server is talking to client */
  300.  
  301.     else {
  302.         if (! FD_ISSET(outsock, &fdset)) {
  303.         perror("weird behavior");
  304.         exit(1);
  305.         }
  306.         if ((rval = read(outsock, buf, 1024)) < 0)
  307.         perror("reading stream message");
  308.         if (rval == 0)
  309.         fprintf(stderr,"Ending server connection\n");
  310.         else {
  311.         write(outfile2, buf, rval);
  312.         write(outfile2, MARK, 6);
  313.         if (write(msgsock, buf, rval) < 0)
  314.             perror("writing on output stream socket");
  315.         }
  316.         }
  317.     } while (rval != 0);
  318.  
  319.  
  320.     /* Close up shop */
  321.  
  322.     fprintf(stderr, "Closing Connections\n");
  323.     close(msgsock);
  324.     close(outsock);
  325.     close(outfile1);
  326.     close(outfile2);
  327.     }
  328. SHAR_EOF
  329. fi # end of overwriting check
  330. #    End of shell archive
  331. exit 0
  332.